package com.eshop.modules.security.config;

import com.eshop.modules.security.security.TokenConfigurer;
import java.util.Iterator;
import java.util.Set;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.AuthenticationEntryPoint;
import javax.servlet.Filter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import java.util.Collection;
import com.eshop.annotation.AnonymousAccess;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import java.util.Map;
import java.util.HashSet;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import org.springframework.context.ApplicationContext;
import com.eshop.modules.security.security.JwtAccessDeniedHandler;
import com.eshop.modules.security.security.JwtAuthenticationEntryPoint;
import org.springframework.web.filter.CorsFilter;
import com.eshop.modules.security.security.TokenUtil;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
    private final TokenUtil tokenUtil;
    private final CorsFilter corsFilter;
    private final JwtAuthenticationEntryPoint authenticationErrorHandler;
    private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
    private final ApplicationContext applicationContext;
    
    public SecurityConfig(final TokenUtil tokenUtil, final CorsFilter corsFilter, final JwtAuthenticationEntryPoint authenticationErrorHandler, final JwtAccessDeniedHandler jwtAccessDeniedHandler, final ApplicationContext applicationContext) {
        this.tokenUtil = tokenUtil;
        this.corsFilter = corsFilter;
        this.authenticationErrorHandler = authenticationErrorHandler;
        this.jwtAccessDeniedHandler = jwtAccessDeniedHandler;
        this.applicationContext = applicationContext;
    }
    
    @Bean
    GrantedAuthorityDefaults grantedAuthorityDefaults() {
        return new GrantedAuthorityDefaults("");
    }
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return (PasswordEncoder)new BCryptPasswordEncoder();
    }
    
    protected void configure(final HttpSecurity httpSecurity) throws Exception {
        final Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = (Map<RequestMappingInfo, HandlerMethod>)((RequestMappingHandlerMapping)this.applicationContext.getBean((Class)RequestMappingHandlerMapping.class)).getHandlerMethods();
        final Set<String> anonymousUrls = new HashSet<String>();
        for (final Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) {
            final HandlerMethod handlerMethod = infoEntry.getValue();
            final AnonymousAccess anonymousAccess = (AnonymousAccess)handlerMethod.getMethodAnnotation((Class)AnonymousAccess.class);
            if (null != anonymousAccess) {
                anonymousUrls.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
            }
        }
        ((HttpSecurity)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((HttpSecurity)((HttpSecurity)((HttpSecurity)((HttpSecurity)httpSecurity.csrf().disable()).addFilterBefore((Filter)this.corsFilter, (Class)UsernamePasswordAuthenticationFilter.class).exceptionHandling().authenticationEntryPoint((AuthenticationEntryPoint)this.authenticationErrorHandler).accessDeniedHandler((AccessDeniedHandler)this.jwtAccessDeniedHandler).and()).headers().frameOptions().disable().and()).sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()).authorizeRequests().antMatchers(HttpMethod.GET, new String[] { "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/webSocket/**" })).permitAll().antMatchers(new String[] { "/swagger-ui.html" })).permitAll().antMatchers(new String[] { "/swagger-resources/**" })).permitAll().antMatchers(new String[] { "/webjars/**" })).permitAll().antMatchers(new String[] { "/*/api-docs" })).permitAll().antMatchers(new String[] { "/v2/api-docs-ext" })).permitAll().antMatchers(new String[] { "/avatar/**" })).permitAll().antMatchers(new String[] { "/websocket/**" })).permitAll().antMatchers(new String[] { "/file/**" })).permitAll().antMatchers(new String[] { "/druid/**" })).permitAll().antMatchers(new String[] { "/api/canvas/**" })).permitAll().antMatchers(new String[] { "/api/checklicense" })).permitAll().antMatchers(HttpMethod.OPTIONS, new String[] { "/**" })).permitAll().antMatchers((String[])anonymousUrls.toArray(new String[0]))).permitAll().anyRequest()).authenticated().and()).apply((SecurityConfigurerAdapter)this.securityConfigurerAdapter());
    }
    
    private TokenConfigurer securityConfigurerAdapter() {
        return new TokenConfigurer(this.tokenUtil);
    }
}
